2023/12/233885字符
Context 上下文
- 上下文:做某一些事情的环境
React 中的上下文特点:
- 当某个组件创建了上下文后,上下文中的数据会被所有后代组件共享
- 如果某个组件依赖了上下文,会导致该组件不再纯粹(外部数据仅来源于属性 props)
简单理解为多层的嵌套函数,在外层函数定义了一个变量贡子函数调用
新版 Context
- 上下文是一个独立于组件的对象,该对象通过 React.createContext() 创建
- 返回的是一个包含两个属性的对象
- Provider : 生产者。一个组件,该组件会创建一个上下文
- Comsumer : 消费者。
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
const ctx = React.createContext();
class Comp extends Component {
state = {
name: 'bozai',
age: 18,
change: () => {
this.setState({
age: 10
})
}
}
render () {
// ctx.Provider 约定谁来提供上下文
return (<ctx.Provider value={this.state}>
<SonComp />
</ctx.Provider>);
}
}
class SonComp extends Component {
shouldComponentUpdate () { // 父组件提供的上下文不会受子组件的影响
return false;
}
render () {
// ctx.Consumer 调用上下文
return (<ctx.Consumer>
{value => <h2>{value.age}
<button onClick={() => value.change()}>change</button>
</h2>}
</ctx.Consumer>);
}
}
ReactDOM.render(<Comp />, document.getElementById('root'));
旧版 Context
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
const types = {
name: PropTypes.string,
age: PropTypes.number
}
class Comp extends Component {
static childContextTypes = types; // 约束上下文中数据的类型
getChildContext () { // 得到上下文中的数据
return {
name: 'bozai',
age: 18
}
}
render () {
return (<SonComp />);
}
}
class SonComp extends Component {
constructor (props, context) {
super(props);
}
static contextTypes = types; // 使用父组件上下文,必须传入静态属性 contextTypes
render () {
console.log(this.context); //--> {name: "bozai", age: 18}
return (<>hello {this.context.name}</>)
}
}
ReactDOM.render(<Comp />, document.getElementById('root'));
子组件更改上下文数据
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
const types = {
name: PropTypes.string,
age: PropTypes.number,
change: PropTypes.func
}
class Comp extends Component {
static childContextTypes = types;
state = {
name: 'bozai',
age: 18
}
getChildContext () {
const self = this;
return {
name: this.state.name,
age: this.state.age,
change (val) {
self.setState({ // 利用 state 来改变数据
age: -- val
})
}
}
}
render () {
return (<SonComp />);
}
}
class SonComp extends Component {
constructor (props, context) {
super(props);
}
static contextTypes = types;
render () {
return (<>
<h1>{this.context.age}</h1>
<button onClick={() => this.context.change(this.context.age)}>age --</button>
</>)
}
}
ReactDOM.render(<Comp />, document.getElementById('root'));
旧版 API 存在严重效率问题,并容易导致滥用